﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace TMRCPUEMULATOR
{

    /// <summary>
    /// Simple assympby class
    /// </summary>
    public class Assembler : IDisposable
    {
        StreamReader sr;
        BinaryWriter bw;


        /// <summary>
        /// initialize a new assembler
        /// </summary>
        /// <param name="Source">source code file name</param>
        public Assembler(string Source)
        {
            sr = new StreamReader(Source);
        }

        /// <summary>
        /// outpout flat binary
        /// </summary>
        /// <param name="Destination">destination output file</param>
        public void OutputBinary(string Destination)
        {

            System.IO.File.Delete(Destination);
            bw = new BinaryWriter(new FileStream(Destination, FileMode.CreateNew,FileAccess.Write));

            string line;
            string[] latex;

            // read a new line
            while (sr.BaseStream.Position<=sr.BaseStream.Length)
            {
 

                line = sr.ReadLine();

                if (!string.IsNullOrEmpty(line))
                {

                    //split to mnimos
                    latex = line.Split(',');
                    
                    //get the opcode for this mnimonic
                    OpCode current = OpCode.LIST.Find(x => x.Name == latex[0]);
                    byte lowdata = 0x00;
                    byte highdata = 0x00;

                    //write a new binary based on the addressing modes
                    switch (current.AddressMode)
                    {

                        case ADDRESSMODE.NONE:
                            bw.Write(current.Binary);

                            break;
                        case ADDRESSMODE.Imeddiate1b:
                            bw.Write(current.Binary);
                            bw.Write((byte)(Convert.ToUInt16(latex[1])));

                            break;
                        case ADDRESSMODE.Direct:
                            bw.Write(current.Binary);          
                            highdata = (byte)(Convert.ToUInt16(latex[1]) >> 8);
                            lowdata = (byte)(Convert.ToUInt16(latex[1]));

                            bw.Write(highdata);
                            bw.Write(lowdata);

                            break;

                        case ADDRESSMODE.Imeddiate2b:
                            bw.Write(current.Binary);
                            highdata = (byte)(Convert.ToUInt16(latex[1]) >> 8);
                            lowdata = (byte)(Convert.ToUInt16(latex[1]));

                            bw.Write(highdata);
                            bw.Write(lowdata);
                            break;
                        default:
                            Console.WriteLine("error " + current.Name);
                            break;
                    }
                }
                else
                {
                    break;
                }
            }
        }

        public void Dispose()
        {
            sr.Close();
            bw.Close();
        }

 
    }
}
